package com.tom.baselibrary.http;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.ArrayMap;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;


// 用户的一套实现。不要使用单例，单例会导致内存泄漏.
public class HttpUtils {
    // 上下文
    private Context mContext;

    // 请求方式：默认get
    private int mType = TYPE_GET;
    public static final int TYPE_POST = 0x0001;
    public static final int TYPE_GET = 0x0000;
    // 参数设置使用链式调用。
    private String mUrl; // 请求的url链接
    private boolean mIsCache = false; // 是否读取缓存
    // 请求参数
    private Map<String, Object> mParams;
    // 主线程的Handler
    public static Handler handler = new Handler(Looper.getMainLooper());


    // 构造方法, 外界不能调用。
    private HttpUtils(Context context) {
        this.mContext = context;
        mParams = new ArrayMap<>(); // ArrayMap区别：比HashMap更高效率
    }

    // 传入context
    public static HttpUtils with(Context context) {
        return new HttpUtils(context);
    }

    public HttpUtils url(String url) {
        this.mUrl = url; // 请求路径
        return this;
    }

    // 请求方式
    public HttpUtils post() {
        this.mType = TYPE_POST;
        return this;
    }

    public HttpUtils get() {
        this.mType = TYPE_GET;
        return this;
    }

    // 添加参数
    public HttpUtils addParam(String key, Object value) {
        this.mParams.put(key, value);
        return this;
    }

    public HttpUtils addParams(Map<String, Object> map) {
        this.mParams.putAll(map);
        return this;
    }
    // 配置需要缓存
    public HttpUtils cache(boolean cache) {
        this.mIsCache = cache;
        return this;
    }
    // TODO 添加请求头 header


    // 添加回调。并执行网络请求
    public void execute(EngineCallback callback) {
        // 每次执行，都要执行这个方法。
        // ..... 添加公共的请求参数。这里由于不包含业务逻辑，所以不能在这里添加。让callBack回调
        // mParams.put("", "");
        if (TextUtils.isEmpty(mUrl)) {
            throw new NullPointerException("访问路径不能为空");
        }
        if (callback == null) {
            callback = EngineCallback.DEFAULT_CALL_BACK; // 默认的callBack
        }
        // 1.baseLibrary里面不包含业务逻辑，所以不能再这里添加 mParams.put()
        // 2.如果有多条业务线，公共参数可能不同。
        // 3.让callback回调去处理。
        callback.onPrepareExecute(mContext, mParams); // 添加所有公共参数，具体的业务逻辑子类自己去实现。

        // 判断执行方法Type类型, 并执行方法。
        if (mType == TYPE_POST) {
            post(mUrl, mParams, callback);
        } else if (mType == TYPE_GET) {
            get(mUrl, mParams, callback);
        }
    }
    // 传入空回调，执行网络请求
    public void execute() {
        execute(null);
    }

    // 默认引擎，OkHttpEngine
    private static IHttpEngine mHttpEngine = null;

    // BaseApplication 中App 初始化配置自己的引擎
    public static void init(IHttpEngine engine) {
        mHttpEngine = engine;
    }

    // 自己带引擎, 让每次请求的引擎可以不一样。
    // HttpUtils.exchangeEngine(new OkHttpEngine())
    public HttpUtils exchangeEngine(IHttpEngine engine) {
        mHttpEngine = engine;
        return this;
    }

    // 不给外部调用
    private void get(String url, Map<String, Object> params, EngineCallback callback) {
        mHttpEngine.get(mContext, url, params, callback, mIsCache);
    }
    private void post(String url, Map<String, Object> params, EngineCallback callback) {
        mHttpEngine.post(mContext, url, params, callback, mIsCache);
    }

    /**
     * 拼接参数
     */
    public static String joinParams(String url, Map<String, Object> params) {
        if (params == null || params.size() <= 0) return url;

        StringBuffer sb = new StringBuffer(url);
        if (!url.contains("?")) {
            sb.append("?");
        } else {
            if (!url.endsWith("?")) {
                sb.append("&");
            }
        }
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            sb.append(entry.getKey() + "=" + entry.getValue() + "&");
        }
        sb.deleteCharAt(sb.length() - 1); // 去掉最后的&
        return sb.toString();
    }

    // 解析类上面的class信息
//    public static Class<?> analysisClazzInfo(Callback httpCallBack) {
    public static Class<?> analysisClazzInfo(Object httpCallBack) {
        Type genType = httpCallBack.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        return (Class<?>) params[0];
    }

    // 取消网络请求
    public void cancelRequest(Object tag) {
//        mHttpEngine.cancelRequest(tag);
    }

}
